package deal

import (
	"encoding/json"
	"fmt"
	"time"
	"week13/errors"
	Repo "week13/internal/data/deal"
	"week13/internal/job"
	"week13/pkg/constant"
	"week13/pkg/orm"
)

var DefaultRepository Repo.DealRepository = &Repo.DealDao{}
type DealDTO struct {
	DealId int64 `json:"dealId"`
	AgentId int64 `json:"agentId"`
	ItemId int64 `json:"itemId"`
	Price int `json:"price"`
	State int `json:"state"`
	RefundState int `json:"refundState"`
	PayState int `json:"payState"`
	GenTime int `json:"genTime"`
	PayTime int `json:"payTime"`
	RefundTime int `json:"refundTime"`
	Addtime int `json:"addtime"`
	Mtime string `json:"mtime"`
	FromEndPoint int `json:"fromEndPoint"`
	PayType int `json:"payType"`
}
type Deal struct {
	DealId int64
	DTO *DealDTO
}
//实例化 XORM 查询转换
func NewDealWhere() Repo.DealWhere{
	return Repo.DealWhere{}
}
//实例化DealDTO
func NewDealDTO(jsonData []byte) (DealDTO,error){
	dto := DealDTO{}
	err := json.Unmarshal(jsonData,&dto)
	if err != nil {
		return DealDTO{},err
	}
	return dto,nil
}
//根据 DealWhere 进行分页查询
func ListByWhere(con Repo.DealWhere,page int,pageSize int) ([]DealDTO,int64,error) {
	xorm := orm.NewXORMTransfer(con)
	ct, err := DefaultRepository.CountByWhere(xorm)
	if err != nil {
		return nil,0,err
	}
	if ct<1 {
		return []DealDTO{},0,nil
	}
	dos, err := DefaultRepository.ListByWhere(xorm,page,pageSize)
	if err != nil {
		return nil,0,err
	}
	dtos := make([]DealDTO,0)
	jsonData,_ := json.Marshal(dos)
	json.Unmarshal(jsonData,&dtos)
	return dtos,ct,nil
}
//创建订单
func CreateDeal(dto DealDTO) (*Deal,error){
	if dto.AgentId<1 || dto.ItemId<1 || dto.FromEndPoint == 0 {
		return nil, errors.NewIllegalParam("create deal params error")
	}
	dto.DealId = 0
	do := DTOToDo(dto)
	do.GenTime = int(time.Now().Unix())
	do.State = 0
	ret,err := DefaultRepository.Save(do)
	if err != nil {
		return nil, errors.NewExecuteFail(err.Error())
	}
	var mq job.SendJobMessage = job.NewKafkaSender(job.TOPIC_DEAL_FINISH)
	msg := job.IncomeCreateMessege{DealId: ret}
	msgJosnData, _ :=json.Marshal(msg)
	err = mq.Send(msgJosnData)
	return NewDeal(ret)
}
//实例化订单数据
func NewDeal (dealId int64) (*Deal,error){
	deal := &Deal{DealId: dealId}
	do, err := DefaultRepository.Find(deal.DealId)
	if err != nil {
		return nil,errors.NewExecuteFail(err.Error())
	}
	dto :=DoToDTO(do)
	deal.DTO = &dto
	return deal,nil
}
//查找一条订单数据
func FindOne(dto DealDTO) (DealDTO,error) {
	filter := DTOToDo(dto)
	do, err := DefaultRepository.FindOneByFilter(filter)
	if err != nil {
		return DealDTO{},errors.NewExecuteFail(err.Error())
	}
	dto = DoToDTO(do)
	return dto,nil
}
//判断是否订单完成
func DealFinish(dto DealDTO) bool {
	if dto.PayState == constant.PAY_STATE_SUCCESS && dto.State==constant.DEAL_STATE_FINISH && dto.RefundState == constant.DEAL_REFUND_INIT {
		return true
	}
	return false
}
//设置订单状态
func (deal *Deal) SetDealState(state int) (int64, error){
	if  state != constant.DEAL_STATE_PAYING || state != constant.DEAL_STATE_OVERDUE {
		return  0, errors.NewIllegalParam("setDealState state illegal")
	}
	data,err := DefaultRepository.Find(deal.DealId)
	if err != nil {
		return 0,err
	}
	if data.State>state {
		return 0, errors.NewIllegalParam(fmt.Sprintf("SetDealState refund state error,now state:%d",data.State) )
	}
	do := Repo.DealDO{State: state}
	return deal.save(do)
}
//设置退款状态
func (deal *Deal) SetRefundState(state int) (int64, error){
	if state != constant.DEAL_REFUND_FAIL || state != constant.DEAL_REFUND_FINISH || state != constant.DEAL_REFUND_ING {
		return  0, errors.NewIllegalParam("SetDealState state illegal")
	}
	data,err := DefaultRepository.Find(deal.DealId)
	if err != nil {
		return 0,err
	}
	if data.State == constant.DEAL_STATE_FINISH {
		return 0, errors.NewIllegalParam("SetDealState deal can't refund because unfinished")
	}
	if data.RefundState> state {
		return 0, errors.NewIllegalParam(fmt.Sprintf("SetDealState refund state error,now state:%d",data.State) )
	}
	do := Repo.DealDO{State: state}
	if data.RefundState == constant.DEAL_REFUND_INIT {
		do.RefundTime = int(time.Now().Unix())
	}
	return deal.save(do)
}
//设置支付信息
func (deal *Deal) SetPayInfo(payState int,payTime int, payType int) (int64,error) {
	if payState != constant.PAY_STATE_SUCCESS || payState != constant.PAY_STATE_FAIL {
		return 0,errors.NewIllegalParam("SetPayInfo payState error")
	}
	if payType != constant.PAY_TYPE_BANK || payType != constant.PAY_TYPE_WX || payType != constant.PAY_TYPE_ALI {
		return 0, errors.NewIllegalParam("SetPayInfo payType error")
	}
	if payTime<1{
		return 0, errors.NewIllegalParam("SetPayInfo payTime error")
	}
    data,err := DefaultRepository.Find(deal.DealId) 
    if err != nil {
    	return 0,err
	}
	if data.PayState == constant.PAY_STATE_SUCCESS {
		return 0,errors.NewIllegalParam("SetPayInfo deal has pay success,can't change")
	}
	do := Repo.DealDO{PayState: payState,PayType: payType,PayTime: payTime}
	if payState == constant.PAY_STATE_SUCCESS {
		do.State = constant.DEAL_STATE_FINISH
	}
	return deal.save(do)
}
//保存
func (deal *Deal) save(do Repo.DealDO)(int64,error){
	do.DealId = deal.DealId
	ret,err := DefaultRepository.Save(do)
	return ret,err
}
func DTOToDo(dto DealDTO) Repo.DealDO{
	jsonData,_ := json.Marshal(dto)
	do := Repo.DealDO{}
	json.Unmarshal(jsonData,&do)
	return do
}
func DoToDTO(do Repo.DealDO) DealDTO {
	jsonData,_ := json.Marshal(do)
	dto := DealDTO{}
	json.Unmarshal(jsonData,&dto)
	return dto
}